(*****************************************************************************
 * Delphi Plug-in Framework (DPF)
 * Copyright (C) 2006-2007 Tao Yuan
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the
 * License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.                                                               }
 *
 * The Initial Developer of the Original Code is Tao Yuan. Portions created by
 * Tao Yuan are Copyright (C) Tao Yuan (taoy.cn att gmail dott com)
 * All rights reserved.
 *****************************************************************************)
 
unit RDStandardPluginLifecycleHandler;

interface

uses
  Rcl,
  RDPluginService,
  RDPluginRegistry, RDPluginLifecycleHandler, RDPluginManager, RDExceptions;

type
  (**
   * Standard implementation of plug-in life cycle handler.
   * <p>
   * <b>Configuration parameters</b>
   * </p>
   * <p>
   * This life cycle handler implementation supports following configuration
   * parameters:
   * <dl>
   *   <dt>probeParentLoaderLast</dt>
   *   <dd>If <code>true</code>, plug-in classloader will try loading classes from
   *     system (boot) classpath <b>after</b> trying to load them from plug-in
   *     classpath. Otherwise system classpath will be used <b>first</b>. Default
   *     value is <code>false</code> that corresponds to standard delegation model
   *     for classloaders hierarchy.</dd>
   * </dl>
   * </p>
   * @version $Id: StandardPluginLifecycleHandler.java,v 1.4 2006/04/09 14:58:04 ddimon Exp $
   *) 
  TStandardPluginLifecycleHandler = class(TPluginLifecycleHandler)
  private
    probeParentLoaderLast: Boolean;
  public
    procedure afterPluginStop(plugin: IPluginInfo); override;
    procedure beforePluginStart(plugin: IPluginInfo); override;
    procedure configure(config: TExtendedProperties); override;
    function createPluginLoader(descr: IPluginDescriptor): TPluginLoader; override;
    function createPluginInstance(descr: IPluginDescriptor): IPluginInfo; override;
  end;

implementation

uses
  SysUtils, Classes,
  RDStandardPluginLoader;

procedure TStandardPluginLifecycleHandler.afterPluginStop(plugin: IPluginInfo);
begin
// no-op
end;

procedure TStandardPluginLifecycleHandler.beforePluginStart(plugin:
    IPluginInfo);
begin
// no-op
end;

procedure TStandardPluginLifecycleHandler.configure(config:
    TExtendedProperties);
begin
  probeParentLoaderLast := StrToBool(config.getProperty('probeParentLoaderLast', 'False')); //$NON-NLS-1$ //$NON-NLS-2$
  log.debug('probeParentLoaderLast parameter value is ' //$NON-NLS-1$
          + BoolToStr(probeParentLoaderLast, True));   
end;

function TStandardPluginLifecycleHandler.createPluginLoader(descr:
    IPluginDescriptor): TPluginLoader;
var
  SPL: TStandardPluginLoader;
begin
  SPL := TStandardPluginLoader.Create(getPluginManager, descr);
  SPL.setProbeParentLoaderLast(probeParentLoaderLast);
  Result := SPL;
end;

function TStandardPluginLifecycleHandler.createPluginInstance(descr:
    IPluginDescriptor): IPluginInfo;
var
  className: string;
begin
  className := descr.getPluginClassName;
//  Class pluginClass;
//  try {
//      pluginClass =
//          getPluginManager().getPluginClassLoader(descr).loadClass(
//                  className);
//  } catch (ClassNotFoundException cnfe) {
//      throw new PluginLifecycleException(
//              StandardObjectFactory.PACKAGE_NAME,
//              "pluginClassNotFound", className, cnfe); //$NON-NLS-1$
//  }
  try
      try
        Result := getPluginManager.getPluginLoader(descr).newPluginInstance;
       except
        on e: Exception do
        begin
          // ignore before 1.0 release
          log.warn('attempt to instantiate Plugin class for plug-in ' //$NON-NLS-1$
                  + descr.getUniqueId() + ' with no-arguments' //$NON-NLS-1$
                  + ' constructor failed, fall-back to the deprecated' //$NON-NLS-1$
                  + ' two-arguments constructor'); //$NON-NLS-1$
//          Result := (Plugin) pluginClass.getConstructor(
//                  new Class[] {PluginManager.class,
//                          PluginDescriptor.class}).newInstance(
//                                  new Object[] {getPluginManager(),
//                                          descr});
         end;
       end;
  except
    on ite: EInvocationTarget do
    begin
//      Throwable t = ite.getTargetException();
//      throw new PluginLifecycleException(
//              StandardObjectFactory.PACKAGE_NAME,
//              'pluginClassInstantiationFailed', descr.getId(), //$NON-NLS-1$
//              (t != null) ? t : ite);
    end;
    on e: Exception do
      raise EPluginLifecycle.Create(
              //StandardObjectFactory.PACKAGE_NAME,
              '',
              'pluginClassInstantiationFailed', descr.getId(), e); //$NON-NLS-1$
  end;
end;

initialization
  RegisterClass(TStandardPluginLifecycleHandler);

end.
